#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include "./my_codeh/lcd.h"		    //  自定义显示屏 头文件  
#include "./my_codeh/event.h"          //  自定义触摸屏 头文件
#include "./my_codeh/block.h"
#include "./my_codeh/speed.h"
#include "./my_codeh/pic.h" 

extern int blocks[ROW][LINE];
int gameover = 0;
int game_started = 0;
int score =0;
int restrat = 0;
int SPEED =800000;

void *flow1(void *arg)      //  流动线程函数 
{   
    LCD l =  *((LCD *)arg);
    BMP *bmp = NULL;
    while(!gameover)
    {   
        usleep(SPEED);
        if(!gameover)
        {
            flow();
        }
        display_init(l.plcd);
        display_all(l.plcd);
        for(int k = 0 ;k<LINE;k ++)
        {
            if(blocks[ROW-1][k]==1)
            {   
                usleep(300000);
                if(blocks[ROW-1][k]==1)
                {
                    gameover =1;
                    printf("有未消灭的黑块，游戏结束！\n");
                    break;
                }
                
            }
        }
    }
    bmp =get_bmp_info("gameover.bmp");
    if(bmp)
    {
        display_bmp_reg(0,0,bmp,l.plcd);
        free_bmp_info(&bmp);
    }
    display_doublelink(0x8DEEEE,l.plcd);
    display_circle(50,50,40,0x00FF7F,l.plcd);
    display_circle(50,290,40,0xD15FEE,l.plcd);
    draw_close_icon(750,50,40,l.plcd);
    draw_plus_icon(750, 290, 40,l.plcd);
    draw_minus_icon(750, 430, 40,l.plcd);
    lcd_show1();
    lcd_show2(score);
}
static void start_btn_click(lv_event_t *event) 
{
    lv_obj_t *btn = lv_event_get_target(event); // 获取触发事件的对象
    if (lv_event_get_code(event) == LV_EVENT_CLICKED) 
    {
        game_started = 1;
        lv_obj_t *cur_scr = lv_scr_act();
        lv_obj_add_flag(cur_scr,LV_OBJ_FLAG_HIDDEN);       //  隐藏 win1
    }
}
// 创建启动界面（图片+按钮）
void create_start_screen() 
{
    // 1. 背景图片
    lv_obj_t *bg_img = lv_img_create(lv_scr_act());
    // 替换为你的图片路径（支持png/jpg等，需提前用LVGL图片转换器处理）
    lv_image_set_src(bg_img,"A:/lingke/gqk.bmp");
    lv_obj_set_size(bg_img, lv_obj_get_width(lv_scr_act()), lv_obj_get_height(lv_scr_act()));
    lv_obj_align(bg_img, LV_ALIGN_CENTER, 0, 0);  // 全屏显示

    // 2. 开始按钮
    lv_obj_t *start_btn = lv_btn_create(lv_scr_act());  // 按钮在图片上方
    lv_obj_set_size(start_btn, 180, 70);  // 按钮大小
    lv_obj_align(start_btn, LV_ALIGN_BOTTOM_MID, 0, -80);  // 底部居中
    lv_obj_set_style_bg_color(start_btn, lv_color_hex(0xFF5722), 0);  // 橙色按钮
    lv_obj_set_style_radius(start_btn, 10, 0);  // 圆角

    // 按钮文字
    lv_obj_t *btn_label = lv_label_create(start_btn);
    lv_label_set_text(btn_label, "PLAY GAME");
    lv_obj_set_style_text_font(btn_label, &lv_font_montserrat_28, 0);
    lv_obj_center(btn_label);
  
    // 绑定点击事件
    lv_obj_add_event_cb(start_btn, start_btn_click, LV_EVENT_CLICKED, NULL);
}

void reset_game(LCD l)
{
    gameover = 0;
    game_started = 0;
    score = 0;
    memset(blocks,0,sizeof(blocks));
    lcd_uninit(&l);
    event_uninit();
}
int main()
{   
    //  1、设备初始化
    if(restrat==0)
{
    lv_init();
    /*Linux frame buffer device init*/
    lv_display_t * disp = lv_linux_fbdev_create();
    lv_linux_fbdev_set_file(disp, "/dev/fb0");
    lv_indev_t * indev = lv_evdev_create(LV_INDEV_TYPE_POINTER,"/dev/input/event0"); 
    init_client_socket(); 
    create_start_screen();
    while(1) 
    {   
        if(game_started==1)
        {
            break;
        }
        lv_timer_handler();
        usleep(5000);
    }
}

    srand((unsigned int)time(NULL));//随机数所需要的前置，保证完全随机
                     //  保存帧缓冲相关信息
    if(lcd_init(&l) == -1 || event_init() == -1)    //  初始化失败,没必要继续
    {
        return -1;
    }
    pthread_t thread;       //  保存新线程的 ID 
    if(pthread_create(&thread,NULL,flow1,&l) != 0)
    {
        printf("pthread_create error\n");
        return -2;
    }

    while(1)//开始接受触摸信息
    {   
        if(gameover!=1)//只要游戏未结束
        {
            EVENT p = get_event();//阻塞形式收集接触信息，同样的另一边的流动进程会进行
            if(gameover==1)//如果使黑块未被消灭的清空，那就要再判断一遍
            {
                break;//这里是怕出现黑块未被清空而导致的（也就是流动进程导致的）gameover==1，且此时进程已经进入这里，则需要判断是否需要终止循环
            }
            if(p.way == MISS)//这里就是触摸边界和灰色方块的情况
            {   
                continue;//不改变情况，继续接收新的触摸信息
            }
            else if(p.way==UNHIT)
            {   
                printf("gameover\n");
                gameover =1;//这里就是触摸到白块，游戏直接终止
                break;
            }
            else if(p.way==HIT)
            {   
                printf("命中!\n");
                score+=1;//计算得分，累加，且作为全局变量，后序lcd要用来显示
                display_all(l.plcd);//这里就是当击中有效黑块后，需要实时显示目前的图像，从而体现出我们击中黑块后，"立即"变成了灰块
                continue;//且继续接收新的触摸信息
            }
        }
    }//除非击中白块，或流动进程中出现gameover==1的情况，则跳出循环，说明此轮游戏结束了
    printf("你的得分为:%d\n",score);//显示得分
    
    //重启装置 
    printf("想再试一次吗？(点击绿色继续一次,点击红色结束游戏)\n");//每轮游戏结束就会进入重启的选项
    while(1)
    {
    EVENT p1 = get_event1();//同样是一轮触摸信息收集，这次收集的就是四种情况
    if(p1.way==HIT)//则说明需要重新开始游戏
    {   
        if(SPEED<0)
        {
            break;
        }
        printf("正在重新开始游戏....\n");
        restrat = 1;//标志位思想，防止重复定义
        reset_game(l);//初始化所有的数据，例如 得分 gameover 以及释放掉所有的lcd event函数，并清空blocks数组 
        return main();//重新回到一开始进行新的一轮游戏
    }
    else if (p1.way==UNHIT)//结束游戏
    {
        printf("即将结束游戏,感谢游玩......\n");
        sleep(2);
        BMP *bmp =get_bmp_info("gameover.bmp");
        display_bmp_reg(0,0,bmp,l.plcd);//显示结束的界面并离开循环
        break;
        
    }

    else if (p1.way==UP)//增加难度，通过函数增加全局变量SPEED，注意SPEED不需要初始化变成初始值，可能玩家重新开始游戏就是为了调整难度，难度要是被初始化不变就没意义了
    {   
        if(SPEED==0)
        {   
            printf("速度为0,不能再快了!\n");
            lcd_show3();//先显示“目前速度为：”
            display_rectangle(492,300,142,33,0x00FF00,l.plcd);//通过每次输出不同数字前先将底部的区域覆盖成一层颜色
            lcd_show4(SPEED);//再显示具体的数字
            continue;
        }
        speed_delete();
        printf("已增大难度......\n");
        lcd_show3();//先显示“目前速度为：”
        display_rectangle(492,300,142,33,0x00FF00,l.plcd);//通过每次输出不同数字前先将底部的区域覆盖成一层颜色
        lcd_show4(SPEED);//再显示具体的数字
        printf("目前速度：%d\n",get_speed());
        continue;//继续接受触摸信息，
    }
    else if (p1.way==DOWN)
    {   
        if(SPEED==9500000)
        {   
            printf("速度为最慢了,不能再慢了!\n");
            lcd_show3();
            display_rectangle(492,300,142,33,0x00FF00,l.plcd);
            lcd_show4(SPEED);
            continue;
        }
        speed_add();
        printf("已减小难度......\n");
        lcd_show3();
        display_rectangle(492,300,142,33,0x00FF00,l.plcd);
        lcd_show4(SPEED);
        printf("目前速度：%d\n",get_speed());
        continue;//同理
    }
    }
    
    printf("游戏结束\n");//此时离开循环，只能说明玩家选择了结束游戏
    //扫尾
    pthread_join(thread, NULL);//！！！！！这里要等待另一边的进程要结束，否则会出现段错误，因为另一边可能还在没有调用完所有的函数
    if(restrat == 1) //说明已经进行了多轮游戏了
    {   
        BMP *bmp1 = get_bmp_info("gameover.bmp");
        if(bmp1) 
        {
            display_bmp_reg(0, 0, bmp1, l.plcd);
            // 确保释放bmp资源
            free_bmp_info(&bmp1);
        }
    }
    lcd_show1();
    lcd_show2(score);//显示得分
    lcd_uninit(&l);//扫尾工作
    event_uninit();
    return 0;

}

